package repository

import (
	"context"
	"fmt"

	"github.com/google/uuid"
	"gorm.io/driver/postgres"
	"gorm.io/gorm"
	"techoiceness.com/aiagent/llm-gateway/internal/entity"
)

// ToolDBConnectionRepository 工具数据库连接仓储接口
type ToolDBConnectionRepository interface {
	CreateConnection(ctx context.Context, connection *entity.ToolDBConnection) error
	GetConnection(ctx context.Context, id uuid.UUID) (*entity.ToolDBConnection, error)
	GetConnectionByName(ctx context.Context, name string) (*entity.ToolDBConnection, error)
	UpdateConnection(ctx context.Context, connection *entity.ToolDBConnection) error
	DeleteConnection(ctx context.Context, id uuid.UUID) error
	ListConnections(ctx context.Context) ([]*entity.ToolDBConnection, error)
	GetEnabledConnections(ctx context.Context) ([]*entity.ToolDBConnection, error)
	GetDefaultConnection(ctx context.Context) (*entity.ToolDBConnection, error)
	SetDefaultConnection(ctx context.Context, id uuid.UUID) error
	TestConnection(ctx context.Context, connection *entity.ToolDBConnection) error
}

// toolDBConnectionRepository 工具数据库连接仓储实现
type toolDBConnectionRepository struct {
	db *gorm.DB
}

// NewToolDBConnectionRepository 创建工具数据库连接仓储
func NewToolDBConnectionRepository(db *gorm.DB) ToolDBConnectionRepository {
	return &toolDBConnectionRepository{db: db}
}

// CreateConnection 创建连接
func (r *toolDBConnectionRepository) CreateConnection(ctx context.Context, connection *entity.ToolDBConnection) error {
	return r.db.WithContext(ctx).Create(connection).Error
}

// GetConnection 获取连接
func (r *toolDBConnectionRepository) GetConnection(ctx context.Context, id uuid.UUID) (*entity.ToolDBConnection, error) {
	var connection entity.ToolDBConnection
	err := r.db.WithContext(ctx).First(&connection, "id = ?", id).Error
	if err != nil {
		return nil, err
	}
	return &connection, nil
}

// GetConnectionByName 根据名称获取连接
func (r *toolDBConnectionRepository) GetConnectionByName(ctx context.Context, name string) (*entity.ToolDBConnection, error) {
	var connection entity.ToolDBConnection
	err := r.db.WithContext(ctx).First(&connection, "name = ?", name).Error
	if err != nil {
		return nil, err
	}
	return &connection, nil
}

// UpdateConnection 更新连接
func (r *toolDBConnectionRepository) UpdateConnection(ctx context.Context, connection *entity.ToolDBConnection) error {
	return r.db.WithContext(ctx).Save(connection).Error
}

// DeleteConnection 删除连接
func (r *toolDBConnectionRepository) DeleteConnection(ctx context.Context, id uuid.UUID) error {
	return r.db.WithContext(ctx).Delete(&entity.ToolDBConnection{}, "id = ?", id).Error
}

// ListConnections 列出所有连接
func (r *toolDBConnectionRepository) ListConnections(ctx context.Context) ([]*entity.ToolDBConnection, error) {
	var connections []*entity.ToolDBConnection
	err := r.db.WithContext(ctx).Order("created_at DESC").Find(&connections).Error
	return connections, err
}

// GetEnabledConnections 获取启用的连接
func (r *toolDBConnectionRepository) GetEnabledConnections(ctx context.Context) ([]*entity.ToolDBConnection, error) {
	var connections []*entity.ToolDBConnection
	err := r.db.WithContext(ctx).Where("is_enabled = ?", true).Order("is_default DESC, created_at DESC").Find(&connections).Error
	return connections, err
}

// GetDefaultConnection 获取默认连接
func (r *toolDBConnectionRepository) GetDefaultConnection(ctx context.Context) (*entity.ToolDBConnection, error) {
	var connection entity.ToolDBConnection
	err := r.db.WithContext(ctx).Where("is_default = ? AND is_enabled = ?", true, true).First(&connection).Error
	if err != nil {
		return nil, err
	}
	return &connection, nil
}

// SetDefaultConnection 设置默认连接
func (r *toolDBConnectionRepository) SetDefaultConnection(ctx context.Context, id uuid.UUID) error {
	return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		// 先将所有连接设为非默认
		if err := tx.Model(&entity.ToolDBConnection{}).Where("is_default = ?", true).Update("is_default", false).Error; err != nil {
			return err
		}
		// 再将指定连接设为默认
		return tx.Model(&entity.ToolDBConnection{}).Where("id = ?", id).Update("is_default", true).Error
	})
}

// TestConnection 测试连接
func (r *toolDBConnectionRepository) TestConnection(ctx context.Context, connection *entity.ToolDBConnection) error {
	// 创建临时数据库连接进行测试
	testDB, err := gorm.Open(postgres.Open(connection.GetDSN()), &gorm.Config{})
	if err != nil {
		return fmt.Errorf("failed to create test connection: %w", err)
	}

	// 测试连接
	sqlDB, err := testDB.DB()
	if err != nil {
		return fmt.Errorf("failed to get underlying sql.DB: %w", err)
	}

	if err := sqlDB.PingContext(ctx); err != nil {
		return fmt.Errorf("connection test failed: %w", err)
	}

	// 关闭测试连接
	if err := sqlDB.Close(); err != nil {
		return fmt.Errorf("failed to close test connection: %w", err)
	}

	return nil
}
